package com.cn.threadpool;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.log4j.Logger;

/**
 * FUN: 在线程池MyThreadPool对象构造初始化时创建该工厂对象，
 * 用来替换默认的工厂，即传入MyThreadPoolExecutor构造方法用作线程构建工厂对象 功能说明： 在JDK ThreadFactory基础上
 * 添加线程运行前、运行后事件及错误日志， 以及获取线程堆栈的方法
 *
 * @author sushy
 * @date 2016-3-23 
 */
public class MyThreadFactory implements ThreadFactory{

	private static final Logger log = Logger.getLogger(MyThreadFactory.class);
	private static final Map<String, Thread> threads = new ConcurrentHashMap<String, Thread>();
	private static final AtomicInteger threadNumber = new AtomicInteger(1);
	private final ThreadGroup group;
	private final String namePrefix;
	private boolean monitor = false;

	public MyThreadFactory(String poolNamePrefix, String poolName) {
		SecurityManager s = System.getSecurityManager();
		if (s != null) {
			group = s.getThreadGroup();
		} else {
			group = Thread.currentThread().getThreadGroup();
		}
		namePrefix = poolNamePrefix + "-" + poolName + "-";
	}

	public Thread newThread(Runnable r) {
		final String name = namePrefix + threadNumber.getAndIncrement();
		initFirstdo(name, null);
		Thread t = null;
		try {
			t = new Thread(group, r, name, 0) {
				public void run() {
					try {
						runFirstDo(name, this);
					} catch (Throwable e) {
						log.error("初始化线程前置工作失败", e);
					}

					try {
						super.run();
					} catch (Throwable e) {
						log.error("线程池运行时失败", e);
						e.printStackTrace();
					} finally {
						runFinallydo(name, this);
					}
				}
			};

			t.setContextClassLoader(Thread.currentThread()
					.getContextClassLoader());
			if (t.isDaemon())
				t.setDaemon(false);
			if (t.getPriority() != Thread.NORM_PRIORITY)
				t.setPriority(Thread.NORM_PRIORITY);
			return t;
		} finally {
			initFinally(name, t);
		}
	}

	/**
	 * 初始化线程前置工作
	 * 
	 * @param name
	 * @param t
	 */
	protected void initFirstdo(String name, Thread t) {
	}

	/**
	 * 线程池运行前置工作
	 * 
	 * @param name
	 * @param t
	 * @throws Exception
	 */
	protected void runFirstDo(String name, Thread t) throws Exception {
	}

	/**
	 * 线程池运行后置工作
	 * 
	 * @param name
	 * @param t
	 */
	protected void runFinallydo(String name, Thread t) {
		threads.remove(name);
	}

	/**
	 * 获取当前线程数
	 * 
	 * @return
	 */
	public int getThreadCount() {
		return threads.size();
	}

	/**
	 * 初始化线程后置工作
	 * 
	 * @param name
	 * @param t
	 */
	protected void initFinally(String name, Thread t) {
		if (monitor) {
			synchronized (threads) {
				try {
					threads.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		threads.put(name, t);
	}

	public List<MyThreadStack> getAllThreadStacks() {
		try {
			monitor = true;
			Object[] os;
			synchronized (threads) {
				os = threads.values().toArray();
				threads.notify();
			}

			List<MyThreadStack> list = new ArrayList<MyThreadStack>();
			if (os == null) {
				return list;
			}

			for (int i = 0; i < os.length; i++) {
				MyThreadStack stack = new MyThreadStack();
				Thread t = (Thread) os[i];
				stack.setName(t.getName());
				t.getId();
				StackTraceElement[] st = t.getStackTrace();
				if (st != null) {
					StringBuffer sb = new StringBuffer();
					for (int j = 0; j < st.length; j++) {
						sb.append(st[j]).append("\n");
					}
					stack.setStack(sb.toString());
				}
				list.add(stack);
			}
			return list;
		} finally {
			monitor = false;
		}
	}


}
